/*
 * CS_REQ_UPGRADE_STONE_COMBINE.cpp
 *
 *  Created on: 2014. 3. 6.
 *      Author: mega
 */

#include "../../User.h"
#include "../../Command.h"
#include "../../GameLog.h"
#include "../../NLogic/Bag.h"
#include "../../NLogic/Item.h"
#include "../../NResource/Static.h"

namespace ProjectZ { namespace NCommand {

static void RecoveryItem(std::vector<NLogic::Item *> & clsItemVector, NLogic::Bag * pBag)
{
	// Bag에서 아이템을 꺼냈기 때문에 만약 에러가 발생하는 경우 다시 Bag으로 넣어준다.
	std::for_each(clsItemVector.begin(), clsItemVector.end(), [&](NLogic::Item * pItem) {
		pBag->AddItem(pItem);
	});
}

static void SendFailUpstoneCombine(User * pUser, int ack)
{
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ack);
	pAck->MakePacket(CMD_SC_REQ_UPGRADE_STONE_COMBINE);
	pUser->Send(pAck);
}

void Command::CS_REQ_UPGRADE_STONE_COMBINE(User * pUser, ::Network::Packet * pPacket)
{
/*	ZNO_CS_REQ_UPGRADE_STONE_COMBINE		0x2208
	{
		u8	count max 8							// 8개의 강화석으로 합성 가능
		{
			u64 u64item_seq;					// 재료 강화석 아이템시퀀스
		}
	}
	ZNO_CS_REQ_UPGRADE_STONE_COMBINE		0x2209
	{
		s16	u16ack;

		s8		class_type;
		u8		sheet_type;
		u16		item_tid;

		u8		level;
		u8		item_quality;

		/// 강화석 효과는 이펙트 1번
		u8		eff_type1;
		u8		eff_pos1;
		s16		eff_value1;
	}*/

	PREPARE_PACKET;

	uint8_t count = 0;

	*pPacket >> count;

	if (8 != count)
	{
		DEBUGLOG("%s : INVALID COUNT=%d", __FUNCTION__, count);
		SendFailUpstoneCombine(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	NLogic::Bag * pBag = pUser->GetBag(BAG_TYPE_ACCESSORY);
	if (NULL == pBag)
	{
		DEBUGLOG("%s : pBag is NULL", __FUNCTION__);
		SendFailUpstoneCombine(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	int itemLevel = 0;
	int itemQuality = 0;
	std::vector<NLogic::Item *> clsItemVector;

	for (int i = 0; i < count; i++)
	{
		uint64_t itemSeq = 0;

		*pPacket >> itemSeq;

		NLogic::Item * pItem = pBag->PopItem(itemSeq);
		if (NULL == pItem)
		{
			DEBUGLOG("%s : pItem is NULL, itemSeq=%lld", __FUNCTION__, itemSeq);
			RecoveryItem(clsItemVector, pBag);
			SendFailUpstoneCombine(pUser, ACK_UNKNOWN_ERROR);
			return;
		}

		// 강화석이 아닌 경우
		if (false == NResource::Static::Instance().GetItemResource()->isUpstone(pItem->GetData()))
		{
			DEBUGLOG("%s : Item is not UpStone!", __FUNCTION__);
			RecoveryItem(clsItemVector, pBag);
			SendFailUpstoneCombine(pUser, ACK_UNKNOWN_ERROR);
			return;
		}

		// 7성 이상 강화석은 합성 불가
		if (6 <= pItem->GetData().quality)
		{
			DEBUGLOG("%s : Item Quality is 7", __FUNCTION__);
			RecoveryItem(clsItemVector, pBag);
			SendFailUpstoneCombine(pUser, ACK_UNKNOWN_ERROR);
			return;
		}

		itemLevel += pItem->GetData().level;
		itemQuality = pItem->GetData().quality;
		clsItemVector.push_back(pItem);
	}

	if (8 != static_cast<int>(clsItemVector.size()))
	{
		DEBUGLOG("%s : INVALID ITEM COUNT!!", __FUNCTION__);
		RecoveryItem(clsItemVector, pBag);
		SendFailUpstoneCombine(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	// 8개 강화석의 등급 검사. (모두 동일 등급이어야 함)
	auto iter = clsItemVector.begin();
	for (; iter != clsItemVector.end(); ++iter)
	{
		if (itemQuality != (*iter)->GetData().quality)
		{
			DEBUGLOG("%s : Item Quality Mismatch", __FUNCTION__);
			RecoveryItem(clsItemVector, pBag);
			SendFailUpstoneCombine(pUser, ACK_UNKNOWN_ERROR);
			return;
		}
	}

	// 레벨은 평균 레벨
	int avgLevel = itemLevel / 8;

	// 골드 검사
	uint32_t needGold = pow(itemQuality + 1, 3) * 1000 * (avgLevel / 10 + 1) * 10;
	if (pUser->GetCharacterInfo().gold < needGold)
	{
		DEBUGLOG("%s : Not Enough Gold", __FUNCTION__);
		RecoveryItem(clsItemVector, pBag);
		SendFailUpstoneCombine(pUser, ACK_NOT_ENOUGH_GOLD);
		return;
	}

	// 등급 상승 여부 결정
	// 등급 상승은 6등급 미만 강화석 합성 인 경우만 수행한다.
	if (5 > itemQuality)
	{
		NResource::UpStoneCombineResource::Flyweight * pFly = NResource::Static::Instance().GetUpStoneCombineResource()->GetFly(itemQuality);
		if (NULL == pFly)
		{
			DEBUGLOG("%s : pFly is NULL", __FUNCTION__);
			RecoveryItem(clsItemVector, pBag);
			SendFailUpstoneCombine(pUser, ACK_UNKNOWN_ERROR);
			return;
		}

		int randRate = rand() % 1000;
		if (randRate < pFly->_RATE)
		{
			itemQuality++;
		}
	}

	// 강화석 생성
	NLogic::Item::Data clsData;
	clsData.level		= avgLevel;
	clsData.quality		= itemQuality;
	clsData.quantity 	= 1;			// 수량
	clsData.tid 		= UPSTONE_TID;	// tid
	clsData.class_type	= -1;			// 장착 클래스 타입
	clsData.sub_type	= CLASS_ITEM_TABLE_ETC;
	clsData.bag_type 	= BAG_TYPE_ACCESSORY;

	// 강화석 데이터 저장
	bool bBagFull = false;
	NLogic::Item * pItem = pBag->AddItemWithData(clsData, bBagFull);
	if (NULL == pItem)
	{
		if (true == bBagFull)
		{
			RecoveryItem(clsItemVector, pBag);
			SendFailUpstoneCombine(pUser, ACK_INVEN_BAG_FULL);
			return;
		}

		DEBUGLOG("%s : pItem is NULL!!", __FUNCTION__);
		RecoveryItem(clsItemVector, pBag);
		SendFailUpstoneCombine(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	// 재료 강화석 삭제 처리
	std::for_each(clsItemVector.begin(), clsItemVector.end(), [&](NLogic::Item * pItem) {
		pItem->DeleteDatabaseItemInfo(NLogic::Item::ItemStatus::EM_ITEM_STATUS_UPSTONE_COMBINE);
	});
	clsItemVector.clear();

	// 응답
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ACK_OK);
	*pAck << static_cast<int8_t>(pItem->GetData().class_type);
	*pAck << static_cast<int8_t>(pItem->GetData().sub_type);
	*pAck << static_cast<uint16_t>(pItem->GetData().tid);
	*pAck << static_cast<uint8_t>(pItem->GetData().level);
	*pAck << static_cast<uint8_t>(pItem->GetData().quality);
	*pAck << static_cast<uint8_t>(pItem->GetData().eff_type[1]);
	*pAck << static_cast<uint8_t>(pItem->GetData().eff_pos[1]);
	*pAck << static_cast<int16_t>(pItem->GetData().eff_value[1]);
	pAck->MakePacket(CMD_SC_REQ_UPGRADE_STONE_COMBINE);
	pUser->Send(pAck);

	// 골드 차감
	NLogic::NFunction::ModifyGold(pUser, needGold * -1);
	NGameLog::LogGoldInfo(pUser, UPSTONE_COMBINE, needGold * -1);
}

} /*NCommand*/ } /*ProjectZ*/
